# -*- coding: utf-8 -*-
#----------------------------------------------------------------------------#
# edict.py
# Lars Yencken <lars.yencken@gmail.com>
# vim: ts=4 sw=4 sts=4 et tw=78:
# Fri Dec  8 14:46:39 2006
#
#----------------------------------------------------------------------------#

""" An interface to dictionaries in the edict format.
"""

#----------------------------------------------------------------------------#

import os
import re
from www import settings
from tools.common import sopen
from tools.smartCache import diskProxy

#----------------------------------------------------------------------------#

_dictionaryDir = os.path.join(settings.DATA_DIR, 'dict')

#----------------------------------------------------------------------------#

class EdictEntry(object):
    """ An entry in an edict-style dictionary.
    """
    __slots__ = ('kanji', 'reading', 'meaning')

    #------------------------------------------------------------------------#
    # PUBLIC METHODS
    #------------------------------------------------------------------------#

    def __init__(self, kanji, reading, meaning):
        """ Constructor.
        """
        self.kanji = kanji
        self.reading = reading
        self.meaning = meaning
        return

    #------------------------------------------------------------------------#

    def __getstate__(self):
        """ The state object to store during pickling.
        """
        return (self.kanji, self.reading, self.meaning)

    #------------------------------------------------------------------------#

    def __setstate__(self, state):
        """ How to recover state after pickling.
        """
        self.kanji, self.reading, self.meaning = state
        return

    #------------------------------------------------------------------------#
    # PRIVATE METHODS
    #------------------------------------------------------------------------#
    
    #------------------------------------------------------------------------#

#----------------------------------------------------------------------------#

class EdictDictionary(dict):
    """ A dictionary in the edict format.
    """

    #------------------------------------------------------------------------#
    # PUBLIC METHODS
    #------------------------------------------------------------------------#

    def __init__(self, filename):
        """ Constructor.
        """
        if not os.path.exists(filename):
            raise Exception, "No such dictionary %s exists" % `filename`

        iStream = sopen(filename)
        header = iStream.readline()

        if not header.startswith(u'？？？？'):
            raise Exception, "Dictionary is not in standard edict format"

        #pattern = re.compile('^([^ ]+) (\[[^ ]+\] )?\/(.*)\/$')
        pattern = re.compile('^([^ ]+) (\[[^\[\]]+\] )?\/(.*)\/$')

        for line in iStream:
            match = pattern.match(line)
            if match is None:
                raise Exception, "Could not parse line: %s" % \
                        line.encode('utf8')

            kanji, reading, meaning = match.groups()

            if reading:
                reading = reading.strip('[] ')
            else:
                reading = kanji

            self.__setitem__(kanji, EdictEntry(kanji, reading, meaning))

        return

    #------------------------------------------------------------------------#

    #------------------------------------------------------------------------#
    # PRIVATE METHODS
    #------------------------------------------------------------------------#
    
    #------------------------------------------------------------------------#

#----------------------------------------------------------------------------#

#@diskProxy(os.path.join(settings.CACHE_DIR, 'edict.cache'), [])
def getDictionary(dictionaryName):
    """ A shortcut which allows you to just specify the dictionary name.
    """
    filename = os.path.join(_dictionaryDir, dictionaryName)
    for maybeFilename in filename, filename + '.gz', filename + '.bz2':
        if os.path.exists(maybeFilename):
            filename = maybeFilename
            break

    return EdictDictionary(filename)

#----------------------------------------------------------------------------#

def listDictionaries():
    """ Returns a list of all available dictionaries in edict format.
    """
    return ['je_edict', 'je_jplaces']

#----------------------------------------------------------------------------#

